﻿/***********************************************************************************************
 * 
 * ProjectName: WMSSoft ShellAPI
 * 
 * Description: Static Reference Class to use ShellAPI - Functions
 * 
 * Created:     27.12.2013
 * 
 * Author:      matthias wagler - matthias@WMSSoft.de
 * 
 * Copyright:   Copyright 2012 by WMSSoft.de
 * 
 * License:     GPLv3
 * 
 * History:     27.12.2013 - matthias wagler matthias@WMSSoft.de   -   Created
 * 
 **********************************************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;

namespace WMSSoft.Lib.Shell
{
    public static class ShellAPI
    {
        #region "advapi32.dll"

        [DllImport("advapi32.dll", CharSet = CharSet.Unicode)]
        public extern static int RegLoadMUIString(IntPtr registryKeyHandle, string value, StringBuilder outputBuffer, 
                                                  int outputBufferSize, out int requiredSize, RegistryLoadMuiStringOptions options, 
                                                  string path);

        #endregion

        #region "coredll.dll"

        [DllImport("coredll.dll")]
        public static extern IntPtr CallWindowProc(IntPtr lpPrevWndFunc, IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);

        #endregion

        #region "ComCtl32.dll"

        [DllImport("ComCtl32.dll", CharSet = CharSet.Auto)]
        public static extern int SetWindowSubclass(IntPtr hWnd, Win32SubClassProc newProc, IntPtr uIdSubclass, IntPtr dwRefData);

        [DllImport("ComCtl32.dll", CharSet = CharSet.Auto)]
        public static extern int RemoveWindowSubclass(IntPtr hWnd, Win32SubClassProc newProc, IntPtr uIdSubclass);

        [DllImport("ComCtl32.dll", CharSet = CharSet.Auto)]
        public static extern int DefSubclassProc(IntPtr hWnd, IntPtr Msg, IntPtr wParam, IntPtr lParam);

#endregion

        #region "kernel32.dll"

        [DllImport("kernel32.dll")]
        public static extern uint GetCurrentProcessId();

        [DllImport("kernel32.dll", CharSet=CharSet.Auto, SetLastError=true)]
        public static extern IntPtr GetModuleHandle(string lpModuleName);

        [DllImport("kernel32.dll", CharSet=CharSet.Auto, SetLastError=true)]
        public static extern IntPtr LoadLibrary([In, MarshalAs(UnmanagedType.LPStr)] string lpFileName);

        #endregion

        #region "Shell32.dll"

        // Retrieves information about an object in the file system,
        // such as a file, a folder, a directory, or a drive root.
        [DllImport("shell32.dll", EntryPoint = "SHGetFileInfo", ExactSpelling = false, CharSet = CharSet.Auto, SetLastError = true)]
        public static extern IntPtr SHGetFileInfo(string pszPath, FILE_ATTRIBUTE dwFileAttributes, ref SHFILEINFO sfi, int cbFileInfo, SHGFI uFlags);

        // Retrieves information about an object in the file system,
        // such as a file, a folder, a directory, or a drive root.
        [DllImport("shell32.dll", EntryPoint = "SHGetFileInfo", ExactSpelling = false, CharSet = CharSet.Auto, SetLastError = true)]
        public static extern IntPtr SHGetFileInfo(IntPtr ppidl, FILE_ATTRIBUTE dwFileAttributes, ref SHFILEINFO sfi, int cbFileInfo, SHGFI uFlags);

        // Takes the CSIDL of a folder and returns the pathname.
        [DllImport("shell32.dll")]
        public static extern Int32 SHGetFolderPath(IntPtr hwndOwner, CSIDL nFolder, IntPtr hToken, SHGFP dwFlags, StringBuilder pszPath);

        // Retrieves the IShellFolder interface for the desktop folder,
        // which is the root of the Shell's namespace. 
        [DllImport("shell32.dll")]
        public static extern Int32 SHGetDesktopFolder(out IntPtr ppshf);

        // Retrieves a pointer to the Shell's IMalloc interface.
        [DllImport("shell32.dll")]
        public static extern Int32 SHGetMalloc(out IntPtr hObject);	// Address of a pointer that receives the Shell's IMalloc interface pointer. 

        // Retrieves ppidl of special folder
        [DllImport("Shell32.dll", EntryPoint = "SHGetSpecialFolderLocation", ExactSpelling = true, CharSet = CharSet.Ansi, SetLastError = true)]
        public static extern Int32 SHGetSpecialFolderLocation(IntPtr hwndOwner, CSIDL nFolder, out IntPtr ppidl);

        [DllImport("shell32.dll", EntryPoint = "ShellExecute")]
        public static extern long ShellExecute(int hwnd, string cmd, string file, string param1, string param2, int swmode);

        [DllImport("shell32.dll")]
        public static extern void SHParseDisplayName([MarshalAs(UnmanagedType.LPWStr)] string name, IntPtr bindingContext, [Out()] out IntPtr pidl, uint sfgaoIn, [Out()] out uint psfgaoOut);

        // This function takes the fully-qualified pointer to an item
        // identifier list (PIDL) of a namespace object, and returns a specified
        // interface pointer on the parent object.
        [DllImport("shell32.dll")]
        public static extern Int32 SHBindToParent(IntPtr pidl, ref Guid riid, out IntPtr ppv, out IntPtr ppidlLast);



        [DllImport("shell32.dll")]
        public static extern IntPtr ExtractAssociatedIcon(IntPtr hinst, string file, ref int index);

        [DllImport("Shell32.dll", CharSet = CharSet.Auto)]
        public extern static int ExtractIconEx([MarshalAs(UnmanagedType.LPTStr)] string lpszFile, int nIconIndex, IntPtr[] phIconLarge, IntPtr[] phIconSmall, int nIcons);

        [DllImport("Shell32.dll", CharSet = CharSet.Auto)]
        public extern static IntPtr ExtractIcon(IntPtr hInst, [MarshalAs(UnmanagedType.LPTStr)] string lpszFile, int nResourceID);

        #endregion

        #region "shlwapi.dll"
       // Accepts a STRRET structure returned by
        // ShellFolder::GetDisplayNameOf that contains or points to a string, and then
        // returns that string as a BSTR.
        [DllImport("shlwapi.dll")]
        public static extern Int32 StrRetToBSTR(
            ref STRRET pstr,        // Pointer to a STRRET structure.
            IntPtr pidl,            // Pointer to an ITEMIDLIST uniquely identifying a file
            // object or subfolder relative
            // to the parent folder.
            [MarshalAs(UnmanagedType.BStr)]
            out String pbstr);      // Pointer to a variable of type BSTR that contains the converted string.

        #endregion
        
        #region "user32.dll"

        [DllImport("user32.dll")]
        public static extern void LockWorkStation();

        [DllImport("user32.dll")]
        public static extern int ExitWindowsEx(int uFlags, int dwReason);


        [DllImport("user32.dll")]
        public static extern int DestroyIcon(IntPtr hIcon);

        // Displays a shortcut menu at the specified location and 
        // tracks the selection of items on the shortcut menu
        [DllImport("user32.dll", ExactSpelling = true, CharSet = CharSet.Auto)]
        public static extern uint TrackPopupMenuEx(IntPtr hmenu,TPM flags,int x,int y,IntPtr hwnd,IntPtr lptpm);

        // Creates a popup-menu. The menu is initially empty, but it can be filled with 
        // menu items by using the InsertMenuItem, AppendMenu, and InsertMenu functions
        [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        public static extern IntPtr CreatePopupMenu();

        // Destroys the specified menu and frees any memory that the menu occupies
        [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        public static extern bool DestroyMenu(IntPtr hMenu);

        // appends a new item to the end of the specified menu bar, drop-down menu, submenu, 
        // or shortcut menu. You can use this function to specify the content, appearance, and 
        // behavior of the menu item
        [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        public static extern bool AppendMenu(IntPtr hMenu, EMFT uFlags, uint uIDNewItem, [MarshalAs(UnmanagedType.LPTStr)] string lpNewItem);

        // Inserts a new menu item into a menu, moving other items down the menu
        [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        public static extern bool InsertMenu(IntPtr hmenu, uint uPosition, EMFT uflags, uint uIDNewItem, [MarshalAs(UnmanagedType.LPTStr)] string lpNewItem);

        // Inserts a new menu item at the specified position in a menu
        [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        public static extern bool InsertMenuItem(IntPtr hMenu, uint uItem, bool fByPosition, ref MENUITEMINFO lpmii);

        [DllImport("user32.dll")]
        public static extern int GetMenuItemCount(IntPtr hMenu);

        // Deletes a menu item or detaches a submenu from the specified menu
        [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        public static extern bool RemoveMenu(IntPtr hMenu, uint uPosition, EMFT uFlags);

        // Retrieves information about a menu item
        [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        public static extern bool GetMenuItemInfo(IntPtr hMenu, uint uItem, bool fByPos, ref MENUITEMINFO lpmii);

        // Changes information about a menu item.
        [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        public static extern bool SetMenuItemInfo(IntPtr hMenu, uint uItem, bool fByPos, ref MENUITEMINFO lpmii);

        // Determines the default menu item on the specified menu
        [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        public static extern int GetMenuDefaultItem(IntPtr hMenu, bool fByPos, uint gmdiFlags);

        // Sets the default menu item for the specified menu
        [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        public static extern bool SetMenuDefaultItem(IntPtr hMenu, uint uItem, bool fByPos);

        // Retrieves a handle to the drop-down menu or submenu activated by the specified menu item
        [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
        public static extern IntPtr GetSubMenu(IntPtr hMenu, int nPos);

        [DllImport("user32.dll", SetLastError = true)]
        public static extern UInt32 GetWindowLong(IntPtr hWnd, int nIndex);

        [DllImport("user32.dll")]
        public static extern int SetWindowLong(IntPtr hWnd, int nIndex, UInt32 dwNewLong);

        // The SendMessage function sends the specified message to a 
        // window or windows. It calls the window procedure for the specified 
        // window and does not return until the window procedure has processed the message. 
        [DllImport("User32.dll")]
        public static extern Int32 SendMessage(
            IntPtr hWnd,               // handle to destination window
            UInt32 Msg,                // message
            IntPtr wParam,             // first message parameter
            IntPtr lParam               // second message parameter
            );

        [DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool GetCursorPos(ref Win32Point pt);

        /// <summary>
        /// Get the window handle from a "Window Class Name" and her Title
        /// </summary>
        /// <param name="className">Window Class Name </param>
        /// <param name="windowText">Window Title</param>
        /// <returns>Window Handle</returns>
        [DllImport("user32.dll")]
        public static extern int FindWindow(string className, string windowText);

        [DllImport("user32.dll", CharSet = CharSet.Unicode)]
        public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr childAfter, string lclassName, string windowTitle);

        [DllImport("user32.dll")]
        public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out IntPtr ProcessId);

        [DllImport("user32.dll")]
        public static extern int ShowWindow(int hwnd, int command);

        [DllImport("user32.dll", EntryPoint = "SetWindowsHookEx", SetLastError = true)]
        public static extern IntPtr SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hMod, uint dwThreadId);

        [DllImport("user32.dll")]
        public static extern int CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);

        [DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool EnumWindows(WindowEnumCallback lpEnumFunc, int lParam);

        [DllImport("user32.dll")]
        public static extern bool EnumThreadWindows(int dwThreadId, EnumThreadDelegate lpfn, IntPtr lParam);

        [DllImport("kernel32.dll")]
        public static extern uint GetCurrentThreadId();

        [DllImport("user32.dll")]
        public static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);

        #endregion

        #region Shell GUIDs

        public static Guid IID_DesktopGUID = new Guid("{00021400-0000-0000-C000-000000000046}");

        public static Guid IID_IShellFolder = new Guid("{000214E6-0000-0000-C000-000000000046}");
        public static Guid IID_IContextMenu = new Guid("{000214e4-0000-0000-c000-000000000046}");
        public static Guid IID_IContextMenu2 = new Guid("{000214f4-0000-0000-c000-000000000046}");
        public static Guid IID_IContextMenu3 = new Guid("{bcfce0a0-ec17-11d0-8d10-00a0c90f2719}");

        public static Guid IID_IDropTarget = new Guid("{00000122-0000-0000-C000-000000000046}");
        public static Guid IID_IDataObject = new Guid("{0000010e-0000-0000-C000-000000000046}");

        public static Guid IID_IQueryInfo = new Guid("{00021500-0000-0000-C000-000000000046}");
        public static Guid IID_IPersistFile = new Guid("{0000010b-0000-0000-C000-000000000046}");

        public static Guid CLSID_DragDropHelper = new Guid("{4657278A-411B-11d2-839A-00C04FD918D0}");
        public static Guid CLSID_NewMenu = new Guid("{D969A300-E7FF-11d0-A93B-00A0C90F2719}");
        public static Guid IID_IDragSourceHelper = new Guid("{DE5BF786-477A-11d2-839D-00C04FD918D0}");
        public static Guid IID_IDropTargetHelper = new Guid("{4657278B-411B-11d2-839A-00C04FD918D0}");

        public static Guid IID_IShellExtInit = new Guid("{000214e8-0000-0000-c000-000000000046}");
        public static Guid IID_IStream = new Guid("{0000000c-0000-0000-c000-000000000046}");
        public static Guid IID_IStorage = new Guid("{0000000B-0000-0000-C000-000000000046}");

        #endregion

        public delegate int Win32SubClassProc(IntPtr hWnd, IntPtr Msg, IntPtr wParam, IntPtr lParam, IntPtr uIdSubclass, IntPtr dwRefData);

        public delegate int HookProc(int code, IntPtr wParam, IntPtr lParam);

        public delegate bool WindowEnumCallback(int hwnd, int lparam);

        public delegate bool EnumThreadDelegate(IntPtr hWnd, IntPtr lParam);
                       
        public const int S_OK = 0;
        public const int S_FALSE = 1;

        public const int MAX_PATH = 260;
        public const uint CMD_FIRST = 1;
        public const uint CMD_LAST = 30000;

        public const string CLASSNAME__REBAR = "ReBarWindow32";
        public const string CLASSNAME__PROGMAN = "Progman";
        public const string CLASSNAME__TASKBAR = "Shell_TrayWnd";

        public static int cbFileInfo = Marshal.SizeOf(typeof(SHFILEINFO));

        public const int WM_PAINT = 15;
        public const int WH_GETMESSAGE = 3;
        public const int WM_CLOSE = 0x0010;
        public const int WM_USER = 0x0400;
        public const int WM_ACTION_STARTMENU = WM_USER + 33;
        public const int WM_ACTION_SET_CALLER = WM_USER + 34;
        public const int WM_ACTION_OPENSETTINGSDLG = WM_USER + 35;
        public const int WM_ACTION_WINKSTART_SHOW = WM_USER + 36;
        public const int WM_ACTION_WINKSTART_HIDE = WM_USER + 37;
        public const int WM_ACTION_WINKSTART_CLOSE = WM_USER + 38;
        public const int WM_ACTION_WINKSTART_NOTIFY_HIDDEN = WM_USER + 39;
        public const int WM_ACTION_BTN_ASK_GUI_LIVES = WM_USER + 40;

        //localized registry string redirection
        // Snippet of ErrorCode.
        public enum ErrorCode
        {
            Success = 0x0000,
            MoreData = 0x00EA
        }
        
        /// <summary>
        ///   Determines the behavior of <see cref="RegLoadMUIString" />.
        /// </summary>
        [Flags]
        public enum RegistryLoadMuiStringOptions : uint
        {
            None = 0,
            /// <summary>
            ///   The string is truncated to fit the available size of the output buffer. If this flag is specified, copiedDataSize must be NULL.
            /// </summary>
            Truncate = 1
        }

    }
}
